package com.zhihao.config;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Redis 客户端，使用 Redisson <a href="https://github.com/redisson/redisson">Redisson</a>
 *
 * @author Jackson
 */
@Configuration
/*
    激活 RedisClientConfigProperties 类的配置绑定功能，并将其注册为 Spring 容器中的 Bean
    使得 RedisClientConfigProperties 的实例可以被注入到其他组件（如 redissonClient 方法）中，从而读取外部配置
*/
@EnableConfigurationProperties(RedisClientConfigProperties.class)
public class RedisClientConfig {

    @Bean("redissonClient")
    public RedissonClient redissonClient(ConfigurableApplicationContext applicationContext, RedisClientConfigProperties properties) {
        Config config = new Config();
        // 根据需要可以设定编解码器；https://github.com/redisson/redisson/wiki/4.-%E6%95%B0%E6%8D%AE%E5%BA%8F%E5%88%97%E5%8C%96
         config.setCodec(JsonJacksonCodec.INSTANCE);
        // 使用 Jackson 序列化编解码器
//        config.setCodec(new JsonJacksonCodec());

        config.useSingleServer()
                .setAddress("redis://" + properties.getHost() + ":" + properties.getPort())
//                .setPassword(properties.getPassword())
                .setConnectionPoolSize(properties.getPoolSize())
                .setConnectionMinimumIdleSize(properties.getMinIdleSize())
                .setIdleConnectionTimeout(properties.getIdleTimeout())
                .setConnectTimeout(properties.getConnectTimeout())
                .setRetryAttempts(properties.getRetryAttempts())
                .setRetryInterval(properties.getRetryInterval())
                .setPingConnectionInterval(properties.getPingInterval())
                .setKeepAlive(properties.isKeepAlive())
        ;

        return Redisson.create(config);
    }

    /*
        自定义 Redis 数据的序列化与反序列化方式。此处使用 JSON 格式（依赖如 FastJSON），可替换为其他序列化方案（如 Kryo、Protobuf）
        ByteBufOutputStream 和 ByteBufInputStream 是 Netty 提供的字节缓冲区操作工具，它们将数据以字节流的形式进行编码和解码。虽然这种方式在性能上可能有一定优势，但它牺牲了数据的可读性。
     */
//    static class RedisCodec extends BaseCodec {
//
//        private final Encoder encoder = in -> {
//            ByteBuf out = ByteBufAllocator.DEFAULT.buffer();
//            try {
//                ByteBufOutputStream os = new ByteBufOutputStream(out);
//                JSON.writeJSONString(os, in, SerializerFeature.WriteClassName);
//                return os.buffer();
//            } catch (IOException e) {
//                out.release();
//                throw e;
//            } catch (Exception e) {
//                out.release();
//                throw new IOException(e);
//            }
//        };
//
//        private final Decoder<Object> decoder = (buf, state) -> JSON.parseObject(new ByteBufInputStream(buf), Object.class);
//
//        @Override
//        public Decoder<Object> getValueDecoder() {
//            return decoder;
//        }
//
//        @Override
//        public Encoder getValueEncoder() {
//            return encoder;
//        }
//
//    }

}
